package com.watermark.ui;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.hardware.Camera;
import android.os.SystemClock;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import com.water_mark.R;
import com.watermark.CameraView;
import com.watermark.IWaterMark;
import com.watermark.ICamera;
import com.watermark.core.utils.ScreenUtil;
import com.watermark.core.utils.UIKit;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class WaterMarkActivity extends AbsPermissionActivity implements View.OnClickListener, SensorController.CameraFocusListener {
    private final static String TAG = "WaterMarkActivity";
    public final static String KEY_CONFIG = "wm_config";
    /**
     * 水印信息构建器
     */
    public static WaterMarkBuilder<?> sWaterMarkBuilder;

    /**
     * 最长录制20s
     */
    public static int sMaxTime = 20;

    /**
     * 拍照后或采集完成是否强制关闭
     */
    public static boolean sForceFinish = false;

    /**
     * 回调
     */
    public static WaterMarkResult sWaterMarkResult;

    private CameraView mCameraView;
    private CircularProgressView mCapture;
    private FocusImageView mFocus;
    private boolean pausing = false;
    private boolean recordFlag = false;//是否正在录制

    private long timeStep = 50;//进度条刷新的时间
    long timeCount = 0;//用于记录录制时间
    private boolean autoPausing = false;
    ExecutorService executorService;

    private final Point sp = ScreenUtil.getScreenPoint();
    private IWaterMark waterMark;
    private WaterMarkConfig config;
    // 录制文件路径集合
    private final List<String> paths = new ArrayList<>();

    public static void openWaterMark(WaterMarkConfig config) {
        Intent intent = new Intent(UIKit.getContext(), WaterMarkActivity.class);
        intent.putExtra(KEY_CONFIG, config);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        UIKit.getContext().startActivity(intent);
    }

    public static void openWaterMark(Activity activity, WaterMarkConfig config, int requestCode) {
        Intent intent = new Intent(activity, WaterMarkActivity.class);
        intent.putExtra(KEY_CONFIG, config);
        activity.startActivityForResult(intent, requestCode);
    }

    protected void closeAndResult(boolean force) {
        if (force || sForceFinish) {
            if (null != sWaterMarkResult) {
                sWaterMarkResult.onResult(paths, "");
            }
            finish();
        }
    }

    protected void deleteCache() {
        if (!TextUtils.isEmpty(lastVideoPath)) {
            File f = new File(lastVideoPath);
            if (f.exists()) {
                f.delete();
            }
            lastVideoPath = "";
        }
    }

    @Override
    public void onBackPressed() {
        if (recordFlag) {
            recordFlag = false;
            deleteCache();
        } else {
            super.onBackPressed();
        }
        closeAndResult(true);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
            if (recordFlag) {
                recordFlag = false;
                deleteCache();
            }
            closeAndResult(true);
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        sWaterMarkBuilder = null;
        sMaxTime = 20;
        sForceFinish = false;
        sWaterMarkResult = null;
        paths.clear();
    }

    @Override
    protected String[] onCheckPermission() {
        return new String[]{Manifest.permission.RECORD_AUDIO,//麦克相关
                Manifest.permission.CAMERA,//麦克相关
        };
    }

    @Override
    protected void onPermissionAccept(boolean accept) {
        setContentView(R.layout.activity_water_mark_camera);
        config = (WaterMarkConfig) getIntent().getSerializableExtra(KEY_CONFIG);
        executorService = Executors.newSingleThreadExecutor();
        SensorController.getInstance().setCameraFocusListener(this);
        initView();
        initConfig();
        // water mark
        updateWaterMark(true);
    }

    void initConfig() {
        if (null == config || null == mCameraView) return;
        mCameraView.setVideoBitRate(config.bitRate);
        mCameraView.setMinSize(config.pictureSize, config.videoSize);
        mCameraView.setFrameRate(config.frameRate);
        // config water mark
        waterMark = mCameraView.getWaterMarkDrawer();
        if (null == waterMark) return;
        waterMark.setWartMarkBackgroundColor(config.tWartMarkBackgroundColor);
        waterMark.setWartMarkTextColor(config.tWartTextColor);
        waterMark.setWartMarkTextSize(config.tWartTextSize);
        waterMark.setWaterMarkOffset(config.offsetX, config.offsetY);
        waterMark.setWaterMarkSize(config.waterMarkWidth, config.waterMarkHeight);
    }

    @SuppressLint("ClickableViewAccessibility")
    private void initView() {
        mCameraView = findViewById(R.id.camera_view);
        mCapture = findViewById(R.id.mCapture);
        mFocus = findViewById(R.id.focusImageView);
        mCapture.setTotal(sMaxTime * 1000);
        mCapture.setOnClickListener(this);
        findViewById(R.id.takePicture).setOnClickListener(this);
        mCameraView.setOnTouchListener((v, event) -> {
            if (mCameraView.getCameraId() == 1) {
                return false;
            }
            if (event.getAction() == MotionEvent.ACTION_UP) {
                float sRawX = event.getRawX();
                float sRawY = event.getRawY();
                float rawY = sRawY * sp.x / sp.y;
                float temp = sRawX;
                float rawX = rawY;
                rawY = (sp.x - temp) * sp.y / sp.x;
                Point point = new Point((int) rawX, (int) rawY);
                mCameraView.onFocus(point, callback);
                mFocus.startFocus(new Point((int) sRawX, (int) sRawY));
            }
            return true;
        });
    }

    void updateWaterMark(boolean init) {
        if (null != config && (config.enableUpdate || init) && null != waterMark && null != sWaterMarkBuilder) {
            Object mark = sWaterMarkBuilder.onBuild();
            if (mark instanceof String) {
                waterMark.setWaterMark(new String[]{(String) mark});
            } else if (mark instanceof String[]) {
                waterMark.setWaterMark((String[]) mark);
            } else if (mark instanceof Bitmap) {
                waterMark.setWaterMark((Bitmap) mark);
            }
        }
    }

    private final Camera.AutoFocusCallback callback = new Camera.AutoFocusCallback() {
        @Override
        public void onAutoFocus(boolean success, Camera camera) {
            //聚焦之后根据结果修改图片
            if (success) {
                mFocus.onFocusSuccess();
            } else {
                //聚焦失败显示的图片
                mFocus.onFocusFailed();
            }
        }
    };

    @Override
    public void onFocus() {
        if (null == mCameraView) return;
        if (mCameraView.getCameraId() == 1) {
            return;
        }
        Point point = new Point(sp.x / 2, sp.y / 2);
        mCameraView.onFocus(point, callback);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (null == mCameraView) return;
        mCameraView.onResume();
        if (recordFlag && autoPausing) {
            mCameraView.resume(true);
            autoPausing = false;
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (null == mCameraView) return;
        if (recordFlag && !pausing) {
            mCameraView.pause(true);
            autoPausing = true;
        }
        mCameraView.onPause();
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (R.id.mCapture == id) {
            if (null == mCameraView) return;
            if (!recordFlag) {
                executorService.execute(recordRunnable);
            } else if (!pausing) {
                mCameraView.pause(false);
                pausing = true;
            } else {
                mCameraView.resume(false);
                pausing = false;
            }
        } else if (R.id.takePicture == id) {
            if (null == mCameraView) return;
            String path = PathUtil.getPicturePath();
            mCameraView.takePicture(path, new ICamera.OnTakePictureResult<Boolean>() {
                @Override
                public void onPictureResult(Boolean flag) {
                    collectComplete(flag ? path : "", false);
                }
            });
        }
    }

    private String lastVideoPath;

    Runnable recordRunnable = new Runnable() {
        @Override
        public void run() {
            recordFlag = true;
            pausing = false;
            autoPausing = false;
            timeCount = 0;
            long time = System.currentTimeMillis();
            lastVideoPath = PathUtil.getVideoPath(time + PathUtil.MP4);
            try {
                mCameraView.startRecord(lastVideoPath);
                while (timeCount <= sMaxTime * 1000L && recordFlag) {
                    if (pausing || autoPausing) {
                        continue;
                    }
                    mCapture.setProcess((int) timeCount);
                    updateWaterMark(false);
                    SystemClock.sleep(timeStep);
                    timeCount += timeStep;
                }
                recordFlag = false;
                mCameraView.stopRecord();
                if (timeCount < 2000) {
                    UIKit.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(activity, "录像时间太短", Toast.LENGTH_SHORT).show();
                        }
                    });
                } else {
                    collectComplete(lastVideoPath, true);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };

    private void collectComplete(final String path, boolean video) {
        UIKit.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (video) {
                    mCapture.setProcess(0);
                }
                Toast.makeText(activity, "文件保存：" + path, Toast.LENGTH_LONG).show();
                paths.add(path);
                closeAndResult(false);
            }
        }, 200);
    }
}
